home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
422_02
/
dosutil
/
validate.c
< prev
Wrap
C/C++ Source or Header
|
1994-03-20
|
9KB
|
259 lines
/**********************************************************************\
VALIDATE - Portable "C" version of a CRC validation program which uses
the same mechanisms as McAfee's VALIDATE program.
Arguments: Filename(s) - The name(s) of the file(s) to be checked.
(See complete documentation following code in this file)
Author: Gary P. Mussar (gmussar on BIX)
This code is released to the public domain. There are no restrictions,
however, acknowledging the author by keeping this comment around would
be appreciated. Compile command: cc validate -fop
\**********************************************************************/
#include <stdio.h>
#include <file.h>
char version[] = {"Portable VALIDATE (Public Domain) V1.0 1991-01-05"};
/**********************************************************************\
The following is used to define the types of variable used to hold or
manipulate CRCs. The 16 bit CRCs require a data type which is at least
16 bits. In addition, the data bits reserved for the CRC must be
manipulated in an unsigned fashion. It is possible to define a data
type which is larger than required to hold the CRC, however, this is an
inefficient use of memory and usually results in less efficient code.
\**********************************************************************/
#define CRC16 unsigned
/**********************************************************************\
The coefficient of each term of the generator polynomial is represented
by a bit in the polynomial array (except for the highest order term
which is always assumed to be 1). The coefficient for the second
highest term in the LSB of the first byte of the polynomial array.
CRC Check 1
Polynomial x^16 + x^15 + x^2 + 1 (16 bit BCS polynomial)
Generator is pre-initialized to 0x0000
CRC Check 2
Polynomial x^16 + x^15 + x^10 + x^3
Generator is pre-initialized to 0x0000
\**********************************************************************/
CRC16 crcchk1[256]; /* Fast lookup table */
CRC16 poly_crcchk1 = {0xA001}; /* Generator polynomial */
CRC16 init_crcchk1 = {0x0000}; /* Pre-init value */
CRC16 crc_crcchk1; /* CRC accumulator */
CRC16 crcchk2[256]; /* Fast lookup table */
CRC16 poly_crcchk2 = {0x1021}; /* Generator polynomial */
CRC16 init_crcchk2 = {0x0000}; /* Pre-init value */
CRC16 crc_crcchk2; /* CRC accumulator */
/* File stuff. The file is read (and CRCs calculated) in chunks. The
size of a chunk is determined by the size of buff[] */
FILE *fp;
char buff[8192];
/**********************************************************************\
Utilities for fast CRC using table lookup
CRC calculations are performed one byte at a time using a table lookup
mechanism. Two routines are provided: one to initialize the CRC lookup
table; and one to perform the CRC calculation over an array of bytes.
A CRC is the remainder produced by dividing a generator polynomial into
a data polynomial using binary arthimetic (XORs). The data polynomial
is formed by using each bit of the data as a coefficient of a term in
the polynomial. These utilities assume the data communications ordering
of bits for the data polynomial, ie. the LSB of the first byte of data
is the coefficient of the highest term of the polynomial, etc..
I_CRC16 - Initialize the 256 entry CRC lookup table based on the
specified generator polynomial.
Input:
Table[256] - Lookup table
GenPolynomial - Generator polynomial
F_CRC16 - Calculate CRC over an array of characters using fast
table lookup.
Input:
Table[256] - Lookup table
*CRC - Pointer to the variable containing the result of
CRC calculations of previous characters. The CRC
variable must be initialized to a known value
before the first call to this routine.
*dataptr - Pointer to array of characters to be included in
the CRC calculation.
count - Number of characters in the array.
\**********************************************************************/
I_CRC16(Table, GenPolynomial)
CRC16 Table[256];
CRC16 GenPolynomial;
{
int i;
CRC16 crc;
for (i = 0; i < 256; ++i)
{
crc = (CRC16) i;
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
Table[i] = crc;
}
}
F_CRC16(Table, CRC, dataptr, count)
CRC16 Table[256];
CRC16 *CRC;
unsigned char *dataptr;
unsigned int count;
{
CRC16 temp_crc;
for (temp_crc = *CRC; count; --count)
{
temp_crc = (temp_crc >> 8) ^ Table[(temp_crc & 0xff) ^ *dataptr++];
}
*CRC = temp_crc;
}
/**********************************************************************\
Mainline
Each file specified on the input line is opened (in binary mode) and two
CRCs are calculated over the data.
The CRC generators are initialized to 0 which means that null bytes (00)
added to the front of a file will not affect the CRC (sigh, when will
people ever learn). Hopefully the file length will catch these kinds of
problems.
\**********************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
unsigned len, files, bcount_h, bcount_l;
fprintf(stderr, "%s\n", version);
/* We expect 1 or more arguments */
if (argc < 2)
{
fprintf(stderr, "This program prints the validation information for a file.\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, " VALIDATE SCAN.EXE\n");
fprintf(stderr, " VALIDATE SCANRES.EXE\n");
exit(1);
}
/* Set up CRC tables */
I_CRC16(crcchk1, poly_crcchk1);
I_CRC16(crcchk2, poly_crcchk2);
/* Loop through each filename on the invocation line */
for (files = 1; files < argc; ++files)
{
printf("\n File Name: %s\n", argv[files]);
fp=open(argv[files],F_READ);
if (!fp)
{
fprintf(stderr, "\n Sorry, I cannot open the input file.\n");
continue;
}
/* Byte count and CRC generators to initial values */
bcount_h = bcount_l = 0;
crc_crcchk1 = init_crcchk1;
crc_crcchk2 = init_crcchk2;
/* Read the file in chunks until done */
while ((len = read(buff, sizeof(buff), fp)) != 0)
{
/* Calculate CRC over this part of file */
F_CRC16(crcchk1, &crc_crcchk1, buff, len);
F_CRC16(crcchk2, &crc_crcchk2, buff, len);
/* Byte count of file */
if((bcount_l += len) > 10000)
++bcount_h, bcount_l -= 10000;
}
/* Give the user the results */
printf(" Size: %u%04u\n", bcount_h, bcount_l);
printf("File Authentication:\n");
printf(" Check Method 1 - %04x\n", crc_crcchk1);
printf(" Check Method 2 - %04x\n", crc_crcchk2);
close(fp);
}
}
/*
Portable VALIDATE is a file authentication program which can be used to
check software for signs of tampering. The program calculates two check
codes over the data in a file by using two different CRC algorithms.
The results can be checked against values provided by the author of the
tested file or a list of values provided by a reliable source. One such
reliable source is the Computer Virus Industry Association which
maintains validation data for various shareware programs on-line. The
CVIA bulletin board can be reached at (408) 988-4004. The user needs to
perform the following steps when validating a program:
- obtain the authentication numbers from a reliable source.
- run Portable VALIDATE against the desired file.
- compare the check codes produced by Portable VALIDATE against the
reliable authentication numbers.
If the numbers match, the user can be reasonably assured that the file
or program has not been corrupte